package demo.rest.portal;

import com.github.pagehelper.PageInfo;
import demo.common.ExceptionStatusConst;
import demo.common.JudgeStatusEnum;
import demo.common.RestResponseEnum;
import demo.entity.Competition;
import demo.entity.Problem;
import demo.entity.User;
import demo.exception.UserUnAuthorizedException;
import demo.producer.JudgeProducer;
import demo.response.ProblemResultDetailVO;
import demo.response.ProblemResultSubmitVO;
import demo.response.RestResponseVO;
import demo.entity.ProblemResult;
import demo.service.*;
import demo.utils.Compare;
import demo.utils.UUIDUtil;
import demo.utils.compareImpl.CPlusPlusCompare;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.annotation.AuthenticationPrincipal;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.stereotype.Controller;
import org.springframework.validation.BindingResult;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;

import javax.servlet.http.HttpServletRequest;
import java.time.Instant;

@Controller
@RequestMapping("/problemResult")
public class ProblemResultController {

    @Autowired
    private ProblemResultService problemResultService;

    @Autowired
    private JudgeProducer producer;

    @Autowired
    private CompetitionService competitionService;

    @Autowired
    private RegisterService registerService;

    @Autowired
    private ProblemService problemService;

    @Autowired
    private JudgeService judgeService;

    /**
     * 跳转到测评记录列表页面
     *
     * @param request
     * @return
     */
    @RequestMapping("/problemResultListPage")
    public String problemResultListPage(HttpServletRequest request) {
        //set data
        request.setAttribute("active4", true);
        return "portal/problemResult/problemResult-list";
    }

    /**
     * 教师 跳转到测评记录列表页面
     * @param request
     * @return
     */
    @RequestMapping("/problemResultListPage2")
    public String problemResultListPage2(HttpServletRequest request) {
        //set data
        request.setAttribute("active4", true);
        return "backend/problemResult/problemResult-list";
    }


    /**
     * 获取题目结果List
     *
     * @param problemId
     * @param pageNum
     * @param pageSize
     * @param name
     * @param type
     * @param status
     * @return
     */
    @RequestMapping("/listProblemResult2Page")
    @ResponseBody
    public RestResponseVO listProblemResult2Page(@RequestParam(required = false) Integer problemId,
                                                 @RequestParam(defaultValue = "1") Integer pageNum,
                                                 @RequestParam(defaultValue = "20") Integer pageSize,
                                                 @RequestParam(defaultValue = "", required = false) String name,
                                                 @RequestParam(defaultValue = "", required = false) String type,
                                                 @RequestParam(defaultValue = "-1", required = false) Integer status) {

        return problemResultService.listProblemResult2Page(problemId, name, type, status, pageNum, pageSize);
    }


    /**
     * 显示源码
     *
     * @param request
     * @param problemResultId
     * @return
     */
    @RequestMapping("/showSourceCodePage")
    public String showSourceCodePage(HttpServletRequest request, Integer problemResultId) {

        //set data
        RestResponseVO<ProblemResult> serverResponse = problemResultService.getById(problemResultId);
        if (serverResponse.isSuccess()) {
            request.setAttribute("sourceCode", serverResponse.getData().getSourceCode());
        } else {
            request.setAttribute("sourceCode", serverResponse.getMsg());
        }
        return "portal/problemResult/source-code";
    }


    /**
     * 提交题目代码
     *
     * @param userDetails
     * @param problemResult
     * @param bindingResult
     * @return runNum
     */
    @RequestMapping("/submit")
    @ResponseBody
    public RestResponseVO<String> submit(@AuthenticationPrincipal UserDetails userDetails, @Validated ProblemResult problemResult, BindingResult bindingResult) {
        if (userDetails == null) {
            return RestResponseVO.createByErrorEnum(RestResponseEnum.UNAUTHORIZED);
        }
        User user = (User) userDetails;
        if (bindingResult.hasErrors()) {
            return RestResponseVO.createByErrorEnum(RestResponseEnum.INVALID_REQUEST);
        }

        if (problemResult.getCompId() != null) {
            Competition competition = competitionService.getById(problemResult.getCompId()).getData();
            if (competition == null) {
                return RestResponseVO.createByErrorEnum(RestResponseEnum.COMPETITION_NOT_FOUND_ERROR);
            }
            Instant nowDate = Instant.now();
            boolean isStarted = nowDate.isAfter(competition.getStartTime().toInstant());
            boolean isClosed = nowDate.isAfter(competition.getEndTime().toInstant());
            if (!isStarted) {
                return RestResponseVO.createByErrorEnum(RestResponseEnum.COMPETITION_NOT_START_ERROR);
            }
            if (isClosed) {
                return RestResponseVO.createByErrorEnum(RestResponseEnum.COMPETITION_CLOSED_ERROR);
            }

            RestResponseVO isRegistered = registerService.isRegisterCompetition(user.getId(), problemResult.getCompId());
            if (!isRegistered.isSuccess()) {
                return RestResponseVO.createByErrorEnum(RestResponseEnum.COMPETITION_NOT_REGISTER);
            }
        }

        //init
        problemResult.setUserId(user.getId());
        problemResult.setStatus(JudgeStatusEnum.QUEUING.getStatus());
        problemResult.setRunNum(UUIDUtil.createByAPI36());

        //   *****    改
        try
        {
            ProblemResult problemResultFromDB = problemService.getProblemResultByRunNum(problemResult.getRunNum());
            if (problemResultFromDB != null) {
                if (problemResultFromDB.getStatus().equals(JudgeStatusEnum.QUEUING.getStatus())
                        || problemResultFromDB.getStatus().equals(JudgeStatusEnum.COMPILING.getStatus())
                        || problemResultFromDB.getStatus().equals(JudgeStatusEnum.JUDGING.getStatus())) {
                    //update compiling
                    problemResult = problemResultFromDB;
                    problemResult.setStatus(JudgeStatusEnum.COMPILING.getStatus());
                    problemService.updateProblemResultById(problemResult);
                } else {

                }
            } else {
                problemResult.setStatus(JudgeStatusEnum.COMPILING.getStatus());
                problemService.insertProblemResult(problemResult);
            }
            //执行编译
            String userDirPath = judgeService.compile(problemResult);

            if (userDirPath != null) {
                //运行
                judgeService.execute(problemResult, userDirPath);
            }
            System.out.println("*****运行成功*******");
            return RestResponseVO.createBySuccess(problemResult.getRunNum());
        }catch (Exception e){
            System.out.println("*****运行失败*******");
            return RestResponseVO.createByErrorMessage("发送异常,请稍后再试," + e.getMessage());
        }

        //   *****   改

//        return producer.send(problemResult);
    }


    /**
     * todo add 金币查看表？
     * 跳转到题目结果页面
     *
     * @param request
     * @param problemResultId
     * @return
     */
    @RequestMapping("/problemResultDetailPage")
    public String problemResultPage(HttpServletRequest request, Integer problemResultId,Integer problemId,
                                    @AuthenticationPrincipal UserDetails userDetails) {
//        System.out.println("***ProblemId***"+problemId+"***problemResultId***"+problemResultId);
        if (userDetails == null) {
            throw new UserUnAuthorizedException(ExceptionStatusConst.USER_UN_AUTHORIZE_EXP, "请先登录");
        }
        User user = (User) userDetails;
        RestResponseVO<ProblemResultDetailVO> restResponseVO = problemResultService.getById2DetailVO(problemResultId);
        ProblemResultDetailVO problemResultDetailVO = restResponseVO.getData();
        if (!problemResultDetailVO.getUserId().equals(user.getId())) {
            if (user.getGoldCount() > 0) {

            } else {

            }
        }
        //set data
//        System.out.println("***code***"+problemResultDetailVO.getSourceCode());
        Problem problem = problemService.getProblemById(problemId);
//        System.out.println("***code***"+problem.getCode());
        double check=0.00;
        if(problem.getCode()!=null&&!problem.getCode().isEmpty()&&problemResultDetailVO.getSourceCode()!=null&&!problemResultDetailVO.getSourceCode().isEmpty())
        {
            Compare compare = new CPlusPlusCompare();   // 代码查重
            check = compare.getSimilarity(problemResultDetailVO.getSourceCode(),problem.getCode());
        }
        check = check*100;
        String c = String.format("%.2f",check);     //保留两位小数
        c = c+"%";
        problemResultDetailVO.setCheck(c);
        request.setAttribute("active4", true);
        request.setAttribute("problemResultDetail", problemResultDetailVO);

        return "portal/problemResult/problemResult-detail";
    }

    /**
     * 教师查看详细情况
     * @param request
     * @param problemResultId
     * @param problemId
     * @param userDetails
     * @return
     */
    @RequestMapping("/problemResultDetailPage2")
    public String problemResultPage2(HttpServletRequest request, Integer problemResultId,Integer problemId,
                                    @AuthenticationPrincipal UserDetails userDetails) {
//        System.out.println("***ProblemId***"+problemId+"***problemResultId***"+problemResultId);
        if (userDetails == null) {
            throw new UserUnAuthorizedException(ExceptionStatusConst.USER_UN_AUTHORIZE_EXP, "请先登录");
        }
        User user = (User) userDetails;
        RestResponseVO<ProblemResultDetailVO> restResponseVO = problemResultService.getById2DetailVO(problemResultId);
        ProblemResultDetailVO problemResultDetailVO = restResponseVO.getData();
        if (!problemResultDetailVO.getUserId().equals(user.getId())) {
            if (user.getGoldCount() > 0) {

            } else {

            }
        }
        //set data
//        System.out.println("***code***"+problemResultDetailVO.getSourceCode());
        Problem problem = problemService.getProblemById(problemId);
//        System.out.println("***code***"+problem.getCode());
        double check=0.00;
        if(problem.getCode()!=null&&!problem.getCode().isEmpty()&&problemResultDetailVO.getSourceCode()!=null&&!problemResultDetailVO.getSourceCode().isEmpty())
        {
            Compare compare = new CPlusPlusCompare();   // 代码查重
            check = compare.getSimilarity(problemResultDetailVO.getSourceCode(),problem.getCode());
        }
        check = check*100;
        String c = String.format("%.2f",check);     //保留两位小数
        c = c+"%";
        problemResultDetailVO.setCheck(c);
        request.setAttribute("active4", true);
        request.setAttribute("problemResultDetail", problemResultDetailVO);

        return "backend/problemResult/problemResult-detail";
    }

    /**
     * 获取题目状态
     *
     * @param runNum
     * @return
     */
    @RequestMapping("/problemResultNow")
    @ResponseBody
    public RestResponseVO<ProblemResultSubmitVO> problemResultNow(String runNum) {
        return problemResultService.getByRunNum2SubmitVO(runNum);
    }


    /**
     * 获取用户比赛提交记录
     * @param userDetails
     * @param pageNum
     * @param pageSize
     * @param compId
     * @return
     */
    @RequestMapping("/listProblemResultCompetitionVO2Page")
    @ResponseBody
    public RestResponseVO<PageInfo> listProblemResultCompetitionVO2Page(@AuthenticationPrincipal UserDetails userDetails,
                                                                        @RequestParam(defaultValue = "1") Integer pageNum,
                                                                        @RequestParam(defaultValue = "10") Integer pageSize,
                                                                        Integer compId) {
        if (userDetails == null) {
            throw new UserUnAuthorizedException(ExceptionStatusConst.USER_UN_AUTHORIZE_EXP, "请先登录");
        }
        User user = ((User) userDetails);

        return problemResultService.listProblemResultCompetitionVO2Page(pageNum, pageSize, user.getId(), compId);
    }

    public static void main(String[] args){
        String s1 = "#include <stdio.h>\n" +
                "\n" +
                "int main() {\n" +
                "    int a,b;\n" +
                "    scanf(\"%d%d\",&a,&b);\n" +
                "    printf(\"%d\", a+b);\n" +
                "    return 0;\n" +
                "}";
        String s2 = "if (LanguageEnum.JAVA8.getType().equals(type)) {\n" +
                "            if (dir != null && !\"\".equals(dir)) {\n" +
                "                return \"javac \" + dir + \"/Main.java\";\n" +
                "            } else {\n" +
                "                return \"javac Main.java\";\n" +
                "            }\n" +
                "        } else if (LanguageEnum.C.getType().equals(type)) {\n" +
                "            if (dir != null && !\"\".equals(dir)) {\n" +
                "                return \"gcc \" + dir + \"/Main.c -o \" + dir + \"/C.out\";\n" +
                "            } else {\n" +
                "                return \"gcc Main.c -o C.out\";\n" +
                "            }\n" +
                "        } else if (LanguageEnum.CPP.getType().equals(type)) {\n" +
                "            if (dir != null && !\"\".equals(dir)) {\n" +
                "                return \"g++ \" + dir + \"/Main.c++ -o \" + dir + \"/C++.out\";\n" +
                "            } else {\n" +
                "                return \"g++ Main.c++ -o C++.out\";\n" +
                "            }\n" +
                "        } else {\n" +
                "            return null;\n" +
                "        }";
        double check;
        Compare compare = new CPlusPlusCompare();
        check = compare.getSimilarity(s1,s2);
        check = check*100;
        String c = String.format("%.2f",check);
        System.out.println(c);
    }


}
